﻿/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#include "SQLStorage.h"

SQLStorageBase::SQLStorageBase()
    : TableName_(NULL)
    , EntryField_(NULL)
    , SrcFormat_(NULL)
    , DstFormat_(NULL)

    , DstFieldCount_(0)
    , SrcFieldCount_(0)
    , RecordCount_(0)
    , MaxEntry_(0)
    , RecordSize_(0)

    , Data_(NULL)
{
}

void SQLStorageBase::Initialize(const char* tableName, const char* entry_field, const char* src_format, const char* dst_format)
{
    TableName_ = tableName;
    EntryField_ = entry_field;
    SrcFormat_ = src_format;
    DstFormat_ = dst_format;

    SrcFieldCount_ = strlen(SrcFormat_);
    DstFieldCount_ = strlen(DstFormat_);
}

char* SQLStorageBase::CreateRecord(std::uint32_t recordId)
{
    char* newRecord = &Data_[RecordCount_ * RecordSize_];
    ++RecordCount_;

    JustCreatedRecord(recordId, newRecord);
    return newRecord;
}

void SQLStorageBase::PrepareToLoad(std::uint32_t maxEntry, std::uint32_t recordCount, std::uint32_t recordSize)
{
    MaxEntry_ = maxEntry;
    RecordSize_ = recordSize;

    delete[] Data_;
    Data_ = new char[recordCount * RecordSize_];
    memset(Data_, 0, recordCount * RecordSize_);

    RecordCount_ = 0;
}

void SQLStorageBase::Free()
{
    if (!Data_) {
        return;
    }

    std::uint32_t _Offset = 0;
    for (std::uint32_t x = 0; x < DstFieldCount_; ++x)
    {
        switch (DstFormat_[x])
        {
        case DBC_FF_LOGIC:
            _Offset += sizeof(bool);
            break;
        case DBC_FF_STRING:
            {
                for (std::uint32_t recordItr = 0; recordItr < RecordCount_; ++recordItr)
                {
                    delete[] * (char**)((char*)(Data_ + (recordItr * RecordSize_)) + _Offset);
                }

                _Offset += sizeof(char*);
                break;
            }
        case DBC_FF_NA:
        case DBC_FF_INT:
            _Offset += sizeof(std::uint32_t);
            break;
        case DBC_FF_BYTE:
        case DBC_FF_NA_BYTE:
            _Offset += sizeof(char);
            break;
        case DBC_FF_FLOAT:
        case DBC_FF_NA_FLOAT:
            _Offset += sizeof(float);
            break;
        case DBC_FF_NA_POINTER:
            // TODO- possible (and small) memleak here possible
            _Offset += sizeof(char*);
            break;
        case DBC_FF_IND:
        case DBC_FF_SORT:
            assert(false && "SQL storage not have sort field types");
            break;
        default:
            assert(false && "unknown format character");
            break;
        }
    }
    delete[] Data_;
    Data_ = NULL;
    RecordCount_ = 0;
}



void SQLStorage::EraseEntry(std::uint32_t id)
{
    Index_[id] = NULL;
}

void SQLStorage::Free()
{
    SQLStorageBase::Free();
    delete[] Index_;
    Index_ = NULL;
}

SQLStorage::SQLStorage(const char* fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, fmt, fmt);
    Index_ = NULL;
}

SQLStorage::SQLStorage(const char* src_fmt, const char* dst_fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, src_fmt, dst_fmt);
    Index_ = NULL;
}

void SQLStorage::PrepareToLoad(std::uint32_t maxRecordId, std::uint32_t recordCount, std::uint32_t recordSize)
{
    // Clear (possible) old data and old index array
    Free();

    // Set index array
    Index_ = new char*[maxRecordId];
    memset(Index_, 0, maxRecordId * sizeof(char*));

    SQLStorageBase::PrepareToLoad(maxRecordId, recordCount, recordSize);
}

void SQLHashStorage::Free()
{
    SQLStorageBase::Free();
    IndexMap_.clear();
}

void SQLHashStorage::PrepareToLoad(std::uint32_t maxRecordId, std::uint32_t recordCount, std::uint32_t recordSize)
{
    // Clear (possible) old data and old index array
    Free();

    SQLStorageBase::PrepareToLoad(maxRecordId, recordCount, recordSize);
}

void SQLHashStorage::EraseEntry(std::uint32_t id)
{
    // do not erase from m_records
    RecordMap::iterator find = IndexMap_.find(id);
    if (find != IndexMap_.end())
    {
        find->second = NULL;
    }
}

SQLHashStorage::SQLHashStorage(const char* fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, fmt, fmt);
}

SQLHashStorage::SQLHashStorage(const char* src_fmt, const char* dst_fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, src_fmt, dst_fmt);
}

void SQLMultiStorage::Free()
{
    SQLStorageBase::Free();
    IndexMultiMap_.clear();
}

void SQLMultiStorage::PrepareToLoad(std::uint32_t maxRecordId, std::uint32_t recordCount, std::uint32_t recordSize)
{
    // Clear (possible) old data and old index array
    Free();

    SQLStorageBase::PrepareToLoad(maxRecordId, recordCount, recordSize);
}

void SQLMultiStorage::EraseEntry(std::uint32_t id)
{
    IndexMultiMap_.erase(id);
}

SQLMultiStorage::SQLMultiStorage(const char* fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, fmt, fmt);
}

SQLMultiStorage::SQLMultiStorage(const char* src_fmt, const char* dst_fmt, const char* _entry_field, const char* sqlname)
{
    Initialize(sqlname, _entry_field, src_fmt, dst_fmt);
}